
const WHITE_LIST = ['/auth/login', '/']
const AntPathMatcher = require('@howiefh/ant-path-matcher')
const jwt = require('jsonwebtoken')
const API_SECRETORKEY = process.env.API_SECRETORKEY
const Api = require('../model/ApiModel')
const Role = require('../model/RoleModel')
const User = require('../model/UserModel')
module.exports = {
  /**
   * 判断是否为一个可以匿名访问的url
   */
  isAnonymous: async function (req, res, next) {
    const pathMatcher = new AntPathMatcher()
    const path = req.path
    let result = true
    const roles = []
    const whitePath = WHITE_LIST.filter((item) => pathMatcher.match(item, path))
    if (whitePath.length > 0) {
      next()
      return
    }

    // 还有第二步
    // TODO: 数据库比对
    // 1. 获取数据库中所有的api
    const apis = await Api.find({ type: 'REQUEST' }).lean()
    // 2. 得到对应的数据库存储的列表
    const matchedApis = apis.filter(api => {
      if (pathMatcher.match(api.path, path) && api.method === req.method) {
        return true
      }
      return false
    })
    console.log('🚀 ~ file: auth.middleware.js ~ line 35 ~ matchedApis', matchedApis)
    // 3. 遍历列表,得到对应role,如果role中明确有Anonymous组,则是可以匿名访问的.
    if (matchedApis.length > 0) {
      const matchedApiIds = matchedApis.map(m => m._id)
      // 通过得到的api,得出该api记录对应的组信息
      const needRoles = await Role.find({
        apiCheckedKeys: { $in: matchedApiIds } // { $elemMatch: { $in: matchedApiIds } }
      })
        // .populate({
        //   path: "apiCheckedKeys",
        //   // match: { _id: { $in: matchedApiIds } }
        // })
        .lean()
      console.log('🚀 ~ file: auth.middleware.js ~ line 44 ~ needRoles ~ needRoles', needRoles)
      if (needRoles.length > 0) {
        // roles.concat(needRoles)
        needRoles.filter(n => {
          roles.push(n.name)
          return true
        })
      }
    }
    // 不处理匿名用户和匿名用户组
    // const isAnonymousRoles = roles.filter((r) => {
    //   if (r.name.toUpperCase() === 'ANONYMOUS') {
    //     return true
    //   }
    //   return false
    // })
    // if (isAnonymousRoles.length > 0) {
    //   result = true
    //   roles = ['ANONYMOUS']
    // }
    if (roles.length > 0) {
      result = false
    }
    req.isAnonymous = result
    req.roles = roles
    console.log('🚀 ~ file: auth.middleware.js ~ line 68 ~ roles: 需要的角色为', roles)
    next()
  },
  authorization: function (req, res, next) {
    // if (req.isAnonymous) { // 可以匿名访问,不需要验证了
    //   next()
    //   return
    // }
    const { authorization } = req.headers
    console.log('🚀 ~ file: auth.middleware.js ~ line 76 ~ req.headers', req.headers)

    let token = ''
    if (authorization && authorization.startsWith('Bearer ')) {
      token = authorization.substr(7)
    }
    console.log('🚀 ~ file: auth.middleware.js ~ line 79 ~ token', token)
    if (token && token.length > 0) {
      const payload = jwt.verify(
        token,
        API_SECRETORKEY,
        {
          ignoreExpiration: false,
          ignoreNotBefore: false
        },
        (error, decoded) => {
          if (error) {
            console.log(error.message)
            throw new Error('token失效,请重新登录')
          }
          return decoded
        }
      )
      const { username } = payload
      console.log('🚀 ~ file: auth.middleware.js ~ line 30 ~ username', username)
      req.user = username
      req.isLogined = true

    // } else {
    //   req.isLogined = false
    //   throw new Error('未登录')
    }
    next()
  },
  // TODO: 判断用户是否有权限
  authentication: async function (req, res, next) {
    const needRoles = req.roles
    const username = req.user
    if (username && needRoles && needRoles.length > 0) {
      const { roles } = await User.findOne({ name: username })
        .populate('roles')
        .lean()
      console.log('🚀 ~ file: auth.middleware.js ~ line 124 ~ roles', req.user, roles)
      const matchedRoles = roles.filter((r) => needRoles.includes(r.name))
      console.log('🚀 ~ file: auth.middleware.js ~ line 126 ~ matchedRoles', matchedRoles)
      if (matchedRoles.length > 0) {
        next()
        return
      } else {
        throw new Error('权限不足')
      }
      // 判断用户是否为Anonymous,组是否为Anonymous
      // if ((roles && roles.length === 0) || user === 'ANONYMOUS') {
      //   req.user = null
      //   req.roles = []
      //   next()
      // }
    } else if (!username && needRoles) {
      throw new Error('权限不足')
    }
    next()
  },
  // 权限检查
  checkAuthentication: async function (req, res, next) {
    // 白名单检查
    const pathMatcher = new AntPathMatcher()
    const path = req.path
    let result = true
    const roles = []
    WHITE_LIST.forEach((item) => {
      if (pathMatcher.match(item, path)) {
        result = true
        req.isAnonymous = result
        roles.push('ANONYMOUS')
        req.roles = roles
        req.user = 'ANONYMOUS'
        next()
      }
    })
    // 数据库查询
    // 分两种情况,在数据库中有(又分两种,一种是定义了权限(组),一种是未定义权限的情况),不在数据库中
    const apiInDb = await Api.find({ type: 'REQUEST' }).lean()
    const matchedApis = apiInDb.filter(api => {
      if (pathMatcher.match(api.path, path)) { // 还有比较方法
        return true
      }
      return false
    })
    if (matchedApis.length === 0) {
      // 匿名访问,未在数据库中定义
      result = true
      req.isAnonymous = result
      roles.push('ANONYMOUS')
      req.roles = roles
      req.user = 'ANONYMOUS'
      next()
    } else {
      // 查询角色
      const matchedApiIds = matchedApis.map((m) => m._id)
      // 通过得到的api,得出该api记录对应的组信息
      const needRoles = await Role.find()
        .populate({
          path: 'apiCheckedKeys',
          match: { _id: { $in: matchedApiIds } }
        })
        .lean()
      if (needRoles.length > 0) {
        needRoles.filter((n) => {
          roles.concat(n.name)
          return true
        })
      }
      const isAnonymousRoles = roles.filter((r) => {
        if (r.name.toUpperCase() === 'ANONYMOUS') {
          return true
        }
        return false
      })
      if (isAnonymousRoles.length > 0) {
        result = true
        req.isAnonymous = result
        roles.push('ANONYMOUS')
        req.roles = roles
        req.user = 'ANONYMOUS'
        next()
      } else {
        // 解析token
        req.isAnonymous = false
        req.roles = roles
        next()
      }
    }
  }
}
